#ifndef errors_h__
#define errors_h__

#include <iosfwd>
#include <stdexcept>
#include <string>
#include "tokenizer.h"

namespace CCompiler
{

    namespace Errors
    {
        class BrokenStream{};
		class EndOfFile{};
		class CmdOptionsError{};
		class BaseErrorWithMsg
		{
		protected:
			std::string msg_;
		public:
			BaseErrorWithMsg(const std::string &msg = ""):
			msg_(msg) {}
			friend std::ostream &operator<<(std::ostream &stream, const BaseErrorWithMsg& error)
			{
			  return stream << error.msg_;
			}			
		};
		class SyntaxError: public BaseErrorWithMsg
		{
            size_t line_, pos_;
		public:
			SyntaxError(const std::string &msg, size_t line = 0, size_t pos = 0): line_(line), pos_(pos), BaseErrorWithMsg(msg) {}
            SyntaxError(const std::string &msg, Token tok): line_(tok.getLine()), pos_(tok.getPos()), BaseErrorWithMsg(msg) {}
            void changeCoordinates(size_t line, size_t pos)
            {
                line_ = line; pos_ = pos;
            }
            void changeCoordinates(Token tok)
            {
                changeCoordinates(tok.getLine(), tok.getPos());
            }
            friend std::ostream &operator<<(std::ostream &stream, const SyntaxError& error)
            {
                return stream << '(' << error.line_ << ", " << error.pos_ << "):Syntax Error:" << error.msg_;
            }            
		};
		class TokenError: public BaseErrorWithMsg
		{
			int line_, pos_;
			std::string originalText_;
		public:
			TokenError(const std::string &msg, int line, int pos, const std::string &originalText):
				BaseErrorWithMsg(msg),
				line_(line),
				pos_(pos),
				originalText_(originalText)
			{}

			friend std::ostream &operator<<(std::ostream &stream, const TokenError& error)
			{
				stream << '[' << error.line_ << ',' << error.pos_ << ']';
				stream << " Type: " << "ERROR";
				stream << " T: " << error.originalText_;
				stream << " S: " << error.msg_;
				return stream << std::endl;
			}			

		};
    }
}

#endif // errors_h__
